package org.zpmis.api.business;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.zpmis.api.http.FileController;
import org.zpmis.common.result.PlatformResult;
import org.zpmis.common.result.ResultCode;
import org.zpmis.config.MinioConfig;
import org.zpmis.util.MinioUtil;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/file")
public class FileBusinessController {
    final static Logger logger = LoggerFactory.getLogger(FileController.class);

    @Autowired
    private MinioUtil minioUtil;

    @Autowired
    private MinioConfig minioConfig;


    /**
     * 获取业务所对应的桶名称
     * 不做默认桶处理 防止业务误传
     * @param business 业务名称
     * @return
     */
    private String getBucketName(String business){
        Assert.notNull(minioConfig.getBusinessBucket(),"minio bucket config error!");
        return minioConfig.getBusinessBucket().get(business);
    }
    /**
     * 上传文件
     * @param business  上传文件的业务名称 需与配置文件一致
     * @param file
     * @return
     */
    @PostMapping("{business}/upload")
    @ResponseBody
    public PlatformResult upload(@RequestParam("file") MultipartFile file, @PathVariable String business) {
        if (file == null) {
            return PlatformResult.builder().code(ResultCode.PARAM_ERROR.code()).msg("file is null").build();
        }
        try {
            String contentType = file.getContentType();
            String originalFilename = file.getOriginalFilename();
            //随机文件UUID名
            String fileName = minioUtil.generateRandomFileName(originalFilename);

            String uploadName = minioUtil.uploadStream(getBucketName(business), fileName, file.getInputStream(), contentType);

            //封装返回信息
            Map<String,String> resultMap = new HashMap<>();
            resultMap.put("originalFilename",originalFilename);
            resultMap.put("uploadName",uploadName);

            return PlatformResult.success(resultMap);
        } catch (Exception e) {
            logger.error("上传服务异常",e);
            return PlatformResult.builder().code(ResultCode.ERROR.code()).msg(e.getMessage()).build();
        }
    }

    /**
     * 下载文件
     * @param business  上传文件的业务名称 需与配置文件一致
     * @param fileName 文件名
     * @param response
     * @return
     */
    @RequestMapping("{business}/download/{filename}")
    public void download(@PathVariable("filename") String fileName, HttpServletResponse response, @PathVariable String business) throws IOException {

        if (StringUtils.isEmpty(fileName)) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
            return ;
        }
        InputStream inputStream = null;
        try {
            inputStream = minioUtil.get(fileName,getBucketName(business));
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setCharacterEncoding("UTF-8");
            response.setContentType(minioUtil.getObjectState(getBucketName(business),fileName).contentType());
            IOUtils.copy(inputStream,response.getOutputStream());
            inputStream.close();

            return ;
        } catch (Exception e) {
            logger.error("下载服务异常",e);
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,e.getMessage());
            return;
        }
    }

    /**
     * 返回图片地址
     *  @param business  上传文件的业务名称 需与配置文件一致
     * @param fileNmae 文件名称
     * @return
     */
    @GetMapping("{business}/img/url/{filename}")
    public String getImgUrl(@PathVariable("filename") String fileNmae, @PathVariable String business,int shareExpiryTime) throws Exception {
        return minioUtil.shareUrl(getBucketName(business),fileNmae, shareExpiryTime);
    }
    /**
     * 在浏览器预览图片
     * @param business  上传文件的业务名称 需与配置文件一致
     * @param fileName 文件名
     * @param response
     * @throws Exception
     */
    @GetMapping("{business}/preViewPicture/{filename}")
    public void preViewPicture(@PathVariable("filename") String fileName, HttpServletResponse response, @PathVariable String business) throws Exception{
        response.setContentType("image/jpeg");
        OutputStream out = null;
        try {
            out = response.getOutputStream();
            InputStream  inputStream = minioUtil.get(fileName,getBucketName(business));
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int n = 0;
            while (-1 != (n = inputStream.read(buffer))) {
                output.write(buffer, 0, n);
            }
            byte[] bytes = output.toByteArray();
            out.write(bytes == null ? new byte[0]:bytes);
            out.flush();
        }finally {
            if (out != null) {
                out.close();
            }
        }
    }

    /**
     * 移除图片
     * @param business  上传文件的业务名称 需与配置文件一致
     * @param fileName 文件名
     * @return
     */
    @GetMapping("{business}/remove/{filename}")
    public PlatformResult remove(@PathVariable("filename") String fileName, @PathVariable String business){
        try {
            minioUtil.remove(fileName,getBucketName(business));
            return PlatformResult.success();
        } catch (Exception e) {
            logger.error("删除文件服务异常",e);
            return PlatformResult.failure(ResultCode.ERROR,e.getMessage());
        }
    }
}
